package com.zzr.demo.rabbitmq.controller;

import com.sun.org.apache.xpath.internal.operations.Bool;
import com.zzr.demo.rabbitmq.model.Dog;
import com.zzr.demo.rabbitmq.model.Person;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

/**
 * @author: xiaomi
 * @date: 2021/8/24
 * @description:
 */
@RestController
public class RabbitMqController {

    @Autowired
    private AmqpAdmin amqpAdmin;


    @Autowired
    private RabbitTemplate rabbitTemplate;


    //region create exchange


    /**
     * create direct exchange
     *
     * @return
     */
    @GetMapping("/createDirectExchange")
    public Boolean createDirectExchange(@RequestParam("name") String name) {
        //持久化，不设置自动删除
        DirectExchange directExchange = new DirectExchange(name, true, false);
        amqpAdmin.declareExchange(directExchange);
        return true;
    }

    /**
     * create fanout exchange
     *
     * @param name
     * @return
     */
    @GetMapping("/createFanoutExchange")
    public Boolean createFanoutExchange(@RequestParam("name") String name) {
        //持久化，不设置自动删除
        FanoutExchange fanoutExchange = new FanoutExchange(name, true, false);
        amqpAdmin.declareExchange(fanoutExchange);
        return true;
    }

    /**
     * create topic exchange
     *
     * @param name
     * @return
     */
    @GetMapping("/createTopicExchange")
    public Boolean createTopicExchange(@RequestParam("name") String name) {
        //持久化，不设置自动删除
        TopicExchange topicExchange = new TopicExchange(name, true, false);
        amqpAdmin.declareExchange(topicExchange);
        return true;
    }

    //endregion

    //region create queue

    /**
     * 创建队列
     *
     * @param name
     * @return
     */
    @GetMapping("/createQueue")
    public Boolean createQueue(@RequestParam("name") String name) {
        //持久化，不设置排他，不设置自动删除，
        //NOTEME:排他队列：当有一个Connection 连上队列后，就不允许其他 Connection 连；一般不设置排他队列
        Queue queue = new Queue(name, true, false, false);
        amqpAdmin.declareQueue(queue);
        return true;
    }

    //endregion

    //region create bindings

    /**
     * 创建绑定（在 exchange 和 queue 之间；还可以在 exchange 和 exchange 之间）
     * 但是队列和队列之间不能 binding
     * NOTEME 绑定的主体必须是 exchange，但是目的地可以是 queue 或者 exchange;route-key 就是 binding-key
     *
     * @param exchange
     * @param queue
     * @param routeKey 路由键
     * @return
     */
    @GetMapping("/createBindingWithQueue")
    public Boolean createBindingWithQueue(@RequestParam("exchange") String exchange, @RequestParam("queue") String queue
            , @RequestParam("routeKey") String routeKey) {

        //全参数说明：
        //目的地；目的地类型；交换机；路由键；自定义参数；
        //将 exchange 与 目的地 通过 路由键进行绑定。
        Binding binding = new Binding(queue,
                Binding.DestinationType.QUEUE,
                exchange,
                routeKey,
                null);
        amqpAdmin.declareBinding(binding);
        return true;
    }

    //endregion

    //region sendMessage


    /**
     * 发送消息
     *
     * @param exchange
     * @param msg
     * @param routeKey 路由键
     * @return
     */
    @GetMapping("/sendDirectMessage")
    public boolean sendDirectMessage(@RequestParam("exchange") String exchange, @RequestParam("msg") String msg, @RequestParam("routeKey") String routeKey) {
        //NOTEME 如果不指定 exchange 那么就是空的！
//        rabbitTemplate.convertAndSend(routeKey, msg);

        rabbitTemplate.convertAndSend(exchange, routeKey, msg);
        return true;
    }

    /**
     * 发送对象消息
     *
     * @param exchange
     * @param routeKey
     * @return
     */
    @GetMapping("/sendEntityMessage")
    public boolean sendEntityMessage(@RequestParam("exchange") String exchange, @RequestParam("routeKey") String routeKey) {
        Person person = new Person("张三", true);
        //当 Person 木有实现序列化接口时，无法通过 jdk 自带的序列化完成传输，有如下异常：
        //SimpleMessageConverter only supports String, byte[] and Serializable payloads, received: com.zzr.demo.rabbitmq.model.Person
        rabbitTemplate.convertAndSend(exchange, routeKey, person);

        return true;
    }


    @GetMapping("/sendDogMessage")
    public boolean sendDogMessage(@RequestParam("exchange") String exchange, @RequestParam("routeKey") String routeKey) {
        Dog dog = new Dog("哈士奇");
        //当 Person 木有实现序列化接口时，无法通过 jdk 自带的序列化完成传输，有如下异常：
        //SimpleMessageConverter only supports String, byte[] and Serializable payloads, received: com.zzr.demo.rabbitmq.model.Person

//        rabbitTemplate.convertAndSend(exchange, routeKey, dog);
        //给消息设置唯一ID
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(exchange, routeKey, dog, correlationData);

        return true;
    }

    //endregion

}
